package com.kfm.base.stream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class PokerGame {

    private Poker poker;

    public PokerGame(boolean hasJoker){
        if (hasJoker){
            poker = new Poker();
        } else {
            poker = new Poker(false);
        }
    }

    public List<List<String>> start(){
        // 扑克牌
        List<Poker.Card> poker = this.poker.getPokers();
        // 洗牌
        for (int i = 0; i < 3; i++) {
            Collections.shuffle(poker);
        }

        // 发牌
        List<Poker.Card> player1 = new ArrayList<>();
        List<Poker.Card> player2 = new ArrayList<>();
        List<Poker.Card> player3 = new ArrayList<>();
        List<String> bottom = List.of(poker.get(51).getString(), poker.get(52).getString(), poker.get(53).getString());

        for (int count = 0, i = 0; count < 17; count ++) {
            player1.add(poker.get(i ++));
            player2.add(poker.get(i ++));
            player3.add(poker.get(i ++));
        }

        // 排序
        List<String> p1 = player1.stream()
                .sorted((a, b) -> a.getOrder() - b.getOrder())
                .map(a -> a.getString())
                .collect(Collectors.toList());

        List<String> p2 = player2.stream()
                .sorted((a, b) -> a.getOrder() - b.getOrder())
                .map(a -> a.getString())
                .collect(Collectors.toList());

        List<String> p3 = player3.stream()
                .sorted((a, b) -> a.getOrder() - b.getOrder())
                .map(a -> a.getString())
                .collect(Collectors.toList());

        // 结果
        List<List<String>> result = List.of(p1, p2, p3, bottom);

        return result;
    }

    public List<List<String>> boom(int num){
        if (num < 2 || num > 17){
            throw new RuntimeException("人数不对");
        }
        List<Poker.Card> pokers = poker.getPokers();

        // 洗牌
        for (int i = 0; i < 3; i ++){
            Collections.shuffle(pokers);
        }

        List<List<String>> list = new ArrayList<>();
        // 发牌
        int index = 0;
        for (int i = 0; i < num; i++) {
            List<Poker.Card> player = new ArrayList<>();
            for (int j = 0; j < 3; j++) {
                player.add(pokers.get(index ++));
            }

            List<String> p = player.stream()
                    .sorted()
                    .map(e -> e.getString())
                    .collect(Collectors.toList());

            list.add(p);
        }

        return list;
    }
}

class Poker {
    // 花色
    private static final List<String> color = List.of("♠", "♥", "♣", "♦");
    // 点数
    private static final List<String> points = List.of("2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3");

    private List<Card> pokers;

    private Boolean hasJoker;

    public Poker(){
        this(true);
    }

    public Poker(boolean hasJoker){
        pokers = new ArrayList<>();
        for (int i = 0; i < color.size(); i++) {
            for (int j = 0; j < points.size(); j++) {
                // order 4 * j + i + j + 2
                pokers.add(new Card(color.get(i), points.get(j), j + 2));
            }
        }

       if (hasJoker){
           // 大小王
           pokers.add(new Card(null, "大王", 0));
           pokers.add(new Card(null, "小王", 1));
       }
    }

    public List<Card> getPokers() {
        return pokers;
    }

    public void setPokers(List<Card> pokers) {
        this.pokers = pokers;
    }


    class Card implements Comparable<Card>{

        private String color;

        private String point;

        private Integer order;

        public Card(String color, String point, Integer order){
            this.color = color;
            this.point = point;
            this.order = order;
        }

        public Integer getOrder(){
            return this.order;
        }

        public String getString(){
            return color == null? point : color + point;
        }

        @Override
        public int compareTo(Card o) {
            return order - o.order;
        }
    }
}
